home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************
- Source file: INTEMPL.C
-
- INCON template input handler.
-
- Compiler: Borland Turbo C 2.01
-
- INCON source files and the object and library files created from
- them are:
- Copyright (c) 1993-94, Richard Zigler.
- You may freely distribute unmodified source, object, and library
- files, and incorporate them into your own non-commercial software,
- provided that this paragraph and the program name and copyright
- strings defined in INCON.C are included in all copies.
- *************************************************************************/
-
- #include <conio.h>
- #include <ctype.h>
- #include <stdio.h>
- #include <string.h>
- #include "indefs.h" /* globals and definitions */
- #include "incon.h" /* state definitions */
- #include "indecl.h" /* public utility routines */
-
- /**** Local Data ****/
-
- typedef enum
- {
- T_INIT , /* initialize template string */
- F_CHAR , /* find first input slot */
- L_CHAR , /* find last input slot */
- N_CHAR , /* find next input slot */
- P_CHAR , /* find previous input slot */
- N_WORD , /* find next input word */
- P_WORD , /* find previous input word */
- S_WORD , /* find start of current word */
- E_WORD , /* find end of current word */
- T_WIPE , /* clear template */
- T_STRIP , /* strip delimiters */
- } TEMPL_OP ; /* template opcodes */
-
- typedef enum
- {
- MIX_DELIM , /* template delimiter */
- MIX_ALPHA , /* alpha input slot */
- MIX_UPPER , /* uppercase input slot */
- MIX_INTGR , /* integer input slot */
- } TEMPL_CHAR ; /* template characters */
-
- /**** Local Routines ****/
-
- static int near pascal TemplateFix
- (
- TEMPL_OP Op, /* operation requested */
- int Pos /* position in source string */
- ) ;
-
- /***********************************************************************/
-
- int pascal hTemplateField( STATES State, register int Pos )
- {
- register int work; /* integer-size working storage */
- BFLAG match; /* character match flag */
-
- switch( State )
- {
- case stError:
- break;
-
- case stQuit: /* [Enter] -- end input */
-
- if ( strchr( OutStr, Fill ) )
- Chr = -1;
- else if ( !(Chr == K_PLUS || Chr == K_MINUS) )
- Chr = 0;
- if ( Flags.Strip )
- TemplateFix( T_STRIP, 0 );
- More = NO;
- break;
-
- case stInit: /* field initialization */
-
- if ( DisplayStr != NULL )
- Pos = TemplateFix( T_INIT, 0 );
- break;
-
- case stFieldClear: /* [Esc] -- clear field or exit */
-
- if ( EscSet )
- More = NO;
- else
- {
- Pos = TemplateFix( T_WIPE, 0 );
- ++Update;
- }
- break;
-
- case stDeleteCharLeft: /* [Backspace] -- delete left */
-
- if ( !(Pos == TemplateFix( F_CHAR, 0 )) )
- {
-
- /* if at last slot in template and not already vacant */
-
- if (OutStr[Pos] != (char)Fill && Pos == TemplateFix(L_CHAR, 0))
- OutStr[Pos] = Fill;
-
- /* else if not at word boundary */
-
- else if ( DisplayStr[Pos - 1] )
- {
- work = TemplateFix( E_WORD, Pos );
- --Pos;
- memcpy( OutStr + Pos, OutStr + Pos + 1, work - Pos );
- OutStr[work] = Fill;
- }
-
- /* else move to last slot in previous word and delete that */
-
- else
- {
- Pos = TemplateFix( P_CHAR, Pos );
- OutStr[Pos] = Fill;
- }
-
- /* if hidden input, fix display here and flag move only */
-
- if ( Flags.Hide )
- {
- PutCursor( Row, Col + Pos );
- putch( Fill );
- --Move;
- }
- else
- ++Update;
- }
- break;
-
- case stMoveToStart: /* [Home] -- start of field */
-
- work = Pos;
- Pos = TemplateFix( F_CHAR, 0 );
- goto __MinusMove;
-
- case stMoveCharLeft: /* [Left Arrow] -- move char lt */
-
- work = Pos;
- Pos = TemplateFix( P_CHAR, Pos );
- goto __MinusMove;
-
- case stMoveCharRight: /* [Right Arrow] -- move char rt */
-
- work = Pos;
- Pos = TemplateFix( N_CHAR, Pos );
- goto __PlusMove;
-
- case stMoveToEnd: /* [End] -- end of field */
-
- work = Pos;
- Pos = TemplateFix( L_CHAR, 0 );
- goto __PlusMove;
-
- case stMoveWordLeft: /* [Ctrl Left] -- move word lt */
-
- work = Pos;
- Pos = TemplateFix( P_WORD, Pos );
-
- __MinusMove:
- ;
- if ( work != Pos )
- --Move;
- break;
-
- case stMoveWordRight: /* [Ctrl Right] -- move word rt */
-
- work = Pos;
- Pos = TemplateFix( N_WORD, Pos );
-
- __PlusMove:
- ;
- if ( work != Pos )
- ++Move;
- break;
-
- case stDeleteWordLeft: /* [Ctrl L] -- delete word left */
-
- if ( !Flags.Hide && !(Pos == TemplateFix( F_CHAR, 0 )) )
- {
- if ( DisplayStr[Pos - 1] ) /* if within word */
- {
- work = Pos;
- Pos = TemplateFix( S_WORD, Pos );
- }
- else /* at word boundary */
- {
- Pos = TemplateFix( P_WORD, Pos );
- work = TemplateFix( E_WORD, Pos );
- }
- memset( OutStr + Pos, Fill, work - Pos + 1 );
- ++Update;
- }
- break;
-
- case stDeleteWordRight: /* [Ctrl R] -- delete word right */
-
- if ( !Flags.Hide && !(Pos == TemplateFix( L_CHAR, 0 )) )
- {
- if ( !DisplayStr[Pos + 1] ) /* if at word boundary */
- Pos = TemplateFix( N_WORD, Pos ); /* move to next word */
- work = TemplateFix( E_WORD, Pos );
- memset( OutStr + Pos, Fill, work - Pos + 1 );
- ++Update;
- }
- break;
-
- case stDeleteToEnd: /* [Ctrl End] -- clear to end */
-
- if ( !(Pos == TemplateFix( L_CHAR, 0 )) )
- {
- TemplateFix( T_WIPE, Pos );
- ++Update;
- }
- break;
-
- case stDeleteToStart: /* [Ctrl Home] -- clear to start */
-
- if ( !(Pos == TemplateFix( F_CHAR, 0 )) )
- {
- Pos = TemplateFix( -(T_WIPE), Pos );
- ++Update;
- }
- break;
-
- case stDeleteAtCursor: /* [Del] -- delete at cursor */
-
- work = TemplateFix( E_WORD, Pos );
- if ( work != Pos )
- memcpy( OutStr + Pos, OutStr + Pos + 1, work - Pos );
- OutStr[work] = Fill;
- ++Update;
- break;
-
- case stExitPlus: /* [Keypad +] -- special exit */
- case stExitMinus: /* [Keypad -] -- special exit */
-
- /****
- Treat these keys as exit requests in integer templates.
- In alpha templates, convert to '+' or '-' and fall through
- to the match state.
- ****/
-
- if ( Flags.Type == INTGR )
- {
- hTemplateField( stQuit, 0 );
- break;
- }
- else
- Chr = (State == stExitPlus) ? '+' : '-' ;
-
- case stCharMatch: /* see if entry matches field */
-
- match = NO;
- work = DisplayStr[Pos];
- if ( work )
- {
- switch( Flags.Type )
- {
- case UPPER:
- __Upper:
- ;
- Chr = toupper( Chr ); /* convert and fall through */
-
- case ALPHA:
- __Alpha:
- ;
- match = Flags.Type == MIXED ? /* if mixed, */
- isalpha( Chr ) : /* match alpha only */
- !iscntrl( Chr ) ; /* else match all */
- break;
-
- case INTGR:
- __Integer:
- ;
- match = isdigit( Chr );
- break;
-
- case MIXED:
-
- if ( work == MIX_ALPHA )
- goto __Alpha;
- else if ( work == MIX_UPPER )
- goto __Upper;
- else
- goto __Integer;
- } /* switch (Type) */
- } /* if (work) */
- if ( match )
- {
- if ( InBegin )
- {
- hTemplateField( stFieldClear, 0 );
- PutCursor( Row, Col );
- cputs( OutStr );
- PutCursor( Row, Col + Pos );
- }
- OutStr[Pos++] = Chr;
- if ( Flags.Hide )
- putch( ' ' );
- if ( !DisplayStr[Pos] )
- Pos = TemplateFix( N_CHAR, Pos );
- ++Update;
- }
- else
- State = stError;
- break;
- } /* switch (State) */
- return( Pos );
- } /**** hTemplateField() ****/
-
- /*************************************************************************
- TemplateFix()
-
- hTemplateField() calls on this routine to initialize template fields
- and manage the cursor within them. During initialization an image
- of the input string passed from the caller is built in DisplayStr,
- which is otherwise unused when the Template flag is set. Each
- "template delimiter" in the input string is represented by a zero
- in DisplayStr; each "input slot" by a non-zero value coded to the
- type of input expected. During other calls, DisplayStr is scanned
- according to the value passed in Op. When a valid input slot is
- found the index into DisplayStr is returned to hTemplateField(),
- which uses that index, in turn, as an index into the template.
- *************************************************************************/
-
- static int near pascal TemplateFix
- (
- TEMPL_OP Op, /* operation requested */
- register int Pos /* position in source string */
- )
- {
- register int i; /* holds chars from InStr for */
- /* T_INIT; indexes DisplayStr */
- /* for other operations */
- int display, /* display default input string? */
- templ_type; /* template type */
- TEMPL_CHAR templ_char; /* character type */
-
- switch( Op )
- {
- case T_INIT:
-
- display = Flags.Display;
- templ_type = Flags.Type;
-
- /****
- Op == T_INIT == 0. Since Op is now available, use
- it to track whether any input slots are defined for
- the template. If, at the end of the for() loop below,
- Op is still 0, the template contains no input slots
- and is invalid.
-
- Note: If the value of T_INIT is defined as other than
- 0, Op must be initialized to 0 prior to the for() loop.
- ****/
-
- for ( Pos = 0 ; Pos < Width ; Pos++ )
- {
- i = LOBYTE(InStr[Pos]);
- templ_char = MIX_DELIM;
-
- /****
- Alpha and upper fields match on any alpha-numeric
- character, including punctuation; integer fields
- match only on decimal integers; mixed input fields
- match only alpha, uppercase alpha, or numeric input.
- ****/
-
- switch ( templ_type )
- {
- case ALPHA:
- case UPPER:
- if ( isalpha(i) )
- templ_char = MIX_ALPHA;
- break;
- case INTGR:
- if ( isdigit(i) )
- templ_char = MIX_INTGR;
- break;
- case MIXED:
- templ_char = isdigit(i) ? MIX_INTGR :
- isupper(i) ? MIX_UPPER :
- isalpha(i) ? MIX_ALPHA :
- MIX_DELIM ;
- break;
- }
- DisplayStr[Pos] = templ_char;
- Op |= templ_char;
- if ( !display && templ_char != MIX_DELIM )
- OutStr[Pos] = Fill;
- } /* for(Pos) */
- DisplayStr[Pos] = '\0';
- if ( !Op ) /* if no input slots, */
- { /* signal invalid template */
- *OutStr = /* for Error() */
- i = 0;
- break;
- } /* else fall through to F_CHAR */
-
- case F_CHAR: /* find first input slot */
-
- i = -1;
- while ( i < Width && !DisplayStr[++i] )
- ;
- if ( i >= Width ) /* if no input slots */
- i = 0; /* put cursor at beginning */
- break;
-
- case L_CHAR: /* find last input slot */
-
- i = Width;
- while ( i > 0 && !DisplayStr[--i] )
- ;
- break;
-
- case N_CHAR: /* find next input slot */
-
- i = Pos;
- while ( i < Width && !DisplayStr[++i] )
- ;
- if ( !DisplayStr[i] )
- while ( i > 0 && !DisplayStr[--i] )
- ;
- break;
-
- case P_CHAR: /* find previous input slot */
-
- i = Pos;
- while ( i > 0 && !DisplayStr[--i] )
- ;
- if ( !DisplayStr[i] )
- while ( i < Width && !DisplayStr[++i] )
- ;
- break;
-
- case N_WORD: /* find next input word */
-
- i = Pos;
- while ( i < Width && DisplayStr[++i] )
- ;
- while ( i < Width && !DisplayStr[++i] )
- ;
- if ( !DisplayStr[i] )
- while ( i > 0 && !DisplayStr[--i] )
- ;
- break;
-
- case P_WORD: /* find previous input word */
-
- i = Pos;
- while ( i > 0 && !DisplayStr[--i] )
- ;
- while ( i > 0 && DisplayStr[--i] )
- ;
- if ( !DisplayStr[i] )
- while ( i < Width && !DisplayStr[++i] )
- ;
- break;
-
- case S_WORD: /* find start of current word */
-
- i = Pos;
- while ( i > 0 && DisplayStr[--i] )
- ;
- ++i;
- break;
-
- case E_WORD: /* find end of current word */
-
- i = Pos;
- while ( i < Width && DisplayStr[++i] )
- ;
- --i;
- break;
-
- case T_WIPE: /* wipe to end of template */
-
- for ( i = Pos ; Pos < Width ; Pos++ )
- if ( DisplayStr[Pos] )
- OutStr[Pos] = Fill;
- if ( !i )
- i = TemplateFix( F_CHAR, 0 );
- break;
-
- case -(T_WIPE): /* wipe to start of template */
-
- for ( i = TemplateFix( F_CHAR, 0 ) ; Pos >= i ; Pos-- )
- if ( DisplayStr[Pos] )
- OutStr[Pos] = Fill;
- break;
-
- case T_STRIP: /* strip delimiters */
-
- for ( i = Pos = 0 ; Pos < Width ; Pos++ )
- if ( DisplayStr[Pos] )
- OutStr[i++] = OutStr[Pos];
- OutStr[i] = '\0';
-
- } /* switch (Op) */
- return ( i );
- } /**** TemplateFix() ****/
-
- /**** EOF: INTEMPL.C ****/